package server.clazzload;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 自定义ClassLoader，动态解密类
 */
public class LagouClassLoader extends ClassLoader{


    // 待动态加载解密的Class的全限定名（包名加类名）
    private String fullyName;

    public LagouClassLoader(){

    }

    @Override
    public Class<?> findClass(String name)  {
        String myPath = name.replace(".","/") + ".class";
        System.out.println(myPath);
        byte[] cLassBytes = getData(myPath);
        Class clazz = defineClass("server.LagouServlet", cLassBytes, 0, cLassBytes.length);
        return clazz;
    }

    private byte[] getData(String className) {
        InputStream is = null;
        try {
            is = new FileInputStream(className);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            byte[] buffer = new byte[2048];
            int num = 0;
            while ((num = is.read(buffer)) != -1) {
                stream.write(buffer, 0, num);
            }
            return stream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    //在动态加载class文件后，需要通过反射才能调用其中方法
    public static void main(String[] args)  {
        LagouClassLoader edClassLoader = new LagouClassLoader();
        Object result = null;
        try {
            Class myClass = edClassLoader.findClass("/Users/zhangshuhan/webapps/demoOne/server/LagouServlet");
            // method1 就是方法名
            Method method = myClass.getDeclaredMethod("init");
            Object obj = myClass.newInstance();
            // result 就是方法返回值
            result = method.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

